﻿using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Timesheet.Common;
using Timesheet.Data.Infrastructure;
using Timesheet.Data.Repository;
using Timesheet.Domain;

namespace Timesheet.Service
{
    public class UserService : IUserService
    {
        private readonly IUserRepository userRepository;
        private readonly IUnitOfWork unitOfWork;
        private readonly IPrjReferencesRepository prjReferencesRepository;
        public ILog Logger { get; private set; }

        public UserService(IUserRepository _userRepository, IPrjReferencesRepository _prjReferencesRepository, IUnitOfWork _unitOfWork)
        {
            this.userRepository = _userRepository;
            this.unitOfWork = _unitOfWork;
            this.prjReferencesRepository = _prjReferencesRepository;
        }


        public IList<Domain.User> getAllUsersForManagement()
        {
            IList<Domain.User> list = userRepository.GetAll().ToList();
            foreach (var user in list)
            {
                user.Password = "CyberVN!23$56";
            }

            return list;
        }


        public IList<Domain.User> getAllUsers()
        {
            return userRepository.GetAll().ToList();
        }



        public IList<User> getAllOrderUsers()
        {
            return userRepository.GetAll().OrderBy(p => p.FirstName).ThenBy(p=>p.LastName).ToList();
        }

        public bool CheckAccountLogin(string username, string encryptPassword)
        {
            User user = userRepository.getUserByUsername(username);
            if (user != null)
            {
                if (user.Password == encryptPassword)
                    return true;
            }
            return false;
        }

        public Domain.User GetByUsername(string p)
        {
            return userRepository.getUserByUsername(p);
            //cook
            //return userRepository.GetAll().FirstOrDefault();
        }


        public void Update(Domain.User info)
        {
            User user = userRepository.GetById(info.Id);

            if (info.Password == "CyberVN!23$56" || info.Password == null)
            {
            }
            else
            {
                user.Password = PasswordUtils.getHashPassword(info.Password);
            }

            user.FirstName = info.FirstName == null ?  "" : info.FirstName.Trim();
            user.LastName = info.LastName == null ? "" : info.LastName.Trim(); 

            if (!string.IsNullOrEmpty(info.Username))
            {
                User duplicate = userRepository.GetAll().FirstOrDefault(u => u.Username.Equals(info.Username) && u.Id != info.Id);
                if (duplicate != null)
                {
                    throw new CustomException("Duplicate username");
                }
            }

            user.Username = info.Username == null ? "" : info.Username.Trim();
            user.Manager = info.Manager;
            user.Coordinator = info.Coordinator;
            user.TeamLead = info.TeamLead;
            user.Active = info.Active;
            userRepository.Update(user);
        }

        public void Save(Domain.User info)
        {
            info.Password = PasswordUtils.getHashPassword(info.Password);
            info.FirstName = info.FirstName == null ?  "" :info.FirstName.Trim();
            info.LastName = info.LastName == null ?  "" :info.LastName.Trim();
            info.Username = info.Username == null ? "" : info.Username.Trim();
            if (!string.IsNullOrEmpty(info.Username))
            {
                User duplicate = userRepository.GetAll().FirstOrDefault(u => u.Username.Equals(info.Username));
                if (duplicate != null)
                {
                    throw new CustomException("Duplicate username");
                }
            }
            userRepository.Add(info);
        }

        public void Delete(long id)
        {
            userRepository.Delete(id);
        }

        public void Delete(Domain.User user)
        {
            if (user != null && user.Id != 0)
            {
                userRepository.Delete(user.Id);
                var lstRef = prjReferencesRepository.GetQuery().Where(x => x.Type == "2" && x.RefID == user.Id).ToList(); ;
                foreach (var item in lstRef)
                {
                    prjReferencesRepository.Delete(item.Id);
                }
            }

        }

        public Domain.User GetUserById(long id)
        {
            return userRepository.GetById(id);
        }

        #region IUserService Members


        public IList<User> GetCoodinators(long prjID)
        {
            var teamRes = new TeamRepository(unitOfWork);
            var teamDetailRes = new TeamDetailRepository(unitOfWork);

            var teams = teamRes.GetQuery().Where(x => x.ProjectID == prjID).Select(x => x.Id);
            var teamDetails = teamDetailRes.GetQuery().Where(x => teams.Contains(x.TeamID)).Select(x => x.EmployerID);
            return userRepository.GetQuery().Where(x => teamDetails.Contains(x.Id) && x.Coordinator).OrderBy(p => p.FirstName).ThenBy(p => p.LastName).ToList();
        }

        public IList<User> GetCoodinators()
        {
            return userRepository.GetQuery().Where(x => x.Coordinator && x.Active).ToList().OrderBy(x => x.FullName).ToList();
        }

        public IList<User> GetCoodinatorsNotInProjectId(long prjID)
        {
            var teamRes = prjReferencesRepository.GetQuery().Where(x => x.ProjID == prjID && x.Type == "2").Select(x => x.RefID);
            return userRepository.GetQuery().Where(x => !teamRes.Contains(x.Id) && x.Coordinator).OrderBy(p => p.FirstName).ThenBy(p => p.LastName).ToList();
        }

        public IList<User> GetTeamLeads(long prjId)
        {
            var teamRes = new TeamRepository(unitOfWork);
            var teamDetailRes = new TeamDetailRepository(unitOfWork);

            var teams = teamRes.GetQuery().Where(x => x.ProjectID == prjId).Select(x => x.Id);
            var teamDetails = teamDetailRes.GetQuery().Where(x => teams.Contains(x.TeamID)).Select(x => x.EmployerID);
            return userRepository.GetQuery().Where(x => teamDetails.Contains(x.Id) && x.TeamLead).OrderBy(p => p.FirstName).ThenBy(p => p.LastName).ToList();
        }

        public void UpdateTeamLead(long prjId, User user)
        {
            var teamRes = new TeamRepository(unitOfWork);
            var teamDetailRes = new TeamDetailRepository(unitOfWork);
            var lstTeam = teamRes.GetQuery().Where(x => x.ProjectID == prjId).ToList();
            if (lstTeam != null)
            {
                foreach (var l in lstTeam)
                {
                    var teamDetail = teamDetailRes.GetQuery().FirstOrDefault(x => x.TeamID == l.Id && x.EmployerID == user.Id);
                    teamDetailRes.Update(teamDetail);
                }
            }
        }

        public void DelPrjLead(long prjId, User user)
        {
            var teamRes = new TeamRepository(unitOfWork);
            var teamDetailRes = new TeamDetailRepository(unitOfWork);
            var lstTeam = teamRes.GetQuery().Where(x => x.ProjectID == prjId).ToList();
            if (lstTeam != null)
            {
                foreach (var l in lstTeam)
                {
                    var teamDetail = teamDetailRes.GetQuery().FirstOrDefault(x => x.TeamID == l.Id && x.EmployerID == user.Id);
                    teamDetailRes.Delete(teamDetail);
                }
            }
        }

        public IList<User> GetTeamLeads()
        {
            return userRepository.GetQuery().Where(x => x.TeamLead && x.Active).ToList().OrderBy(x => x.FullName).ToList();
        }

        #endregion

        public List<User> GetActivedCoodinators(long prjID)
        {
            var teamRes = prjReferencesRepository.GetQuery().Where(x => x.ProjID == prjID && x.Type == "2").Select(x => x.RefID);
            return userRepository.GetQuery().Where(x => teamRes.Contains(x.Id) && x.Coordinator && x.Active == true).ToList();
        }


    }
}
